﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Text;

namespace EdgeStatz.ESSystems.Objects
{
    public class ES_R_Report
    {
        string report_name;
        string report_path;
        List<string> data_sets_to_run = new List<string> { };

        ES_R_DataSourceCollection data_sources = new ES_R_DataSourceCollection();
        ES_R_DataSetCollection data_sets = new ES_R_DataSetCollection();
        ES_R_ReportParameterCollection report_parameters = new ES_R_ReportParameterCollection();

        public string Name { get { return report_name; } set { report_name = value; } }
        public string Path { get { return report_path; } set { report_path = value; } }
        public List<string> DataSetsToRun { get { return data_sets_to_run; } set { data_sets_to_run = value; } }

        public ES_R_DataSourceCollection DataSources { get { return data_sources; } }
        public ES_R_DataSetCollection DataSets { get { return data_sets; } }
        public ES_R_ReportParameterCollection ReportParameters { get { return report_parameters; } }

        public DataTable GetTableForDataSet(string name)
        {
            int index = GetDataSetIndex(name);
            if (index == -1)
                throw new Exception("Dataset [" + name + "] not found.");
            object[] param = null;
            if (data_sets[index].Parameters.Count > 0)
            {
                param = new object[data_sets[index].Parameters.Count];
                for (int j = 0; j < data_sets[index].Parameters.Count; j++)
                {
                    try { param[j] = GetReportParameterValue(data_sets[index].Parameters[j].Value); }
                    catch (NullReferenceException ex)
                    {
                        return null;
                    }
                }
            }

            DataTable table = new DataTable(data_sets[index].Name);
            foreach (ES_R_DataField df in data_sets[index].Fields)
                table.Columns.Add(new DataColumn(df.DataField, df.Type));

            object[] data = null;
            if (data_sets[index].Parameters.Count == 0)
                data = GlobalObjectsSQL.ExecuteReaderQueryCommand(data_sets[index].CommandText);
            else
            {
                if (param == null || param.Length != data_sets[index].Parameters.Count)
                    throw new Exception("parameters are null or the count doesn't match the number of required parameters.");
                string sqlcmd = data_sets[index].CommandText;
                for (int j = 0; j < param.Length; j++)
                    sqlcmd = sqlcmd.Replace(data_sets[index].Parameters[j].Name, GlobalObjectsSQL.ReturnForDataEntry(param[j]));
                data = GlobalObjectsSQL.ExecuteReaderQueryCommand(sqlcmd);
            }
            if (data != null)
                foreach (object obj in data)
                    table.LoadDataRow((object[])obj, true);
            
            data_sets[index].Table = table;
            return table;
        }

        public void Refresh_ParamTables()
        {
            for (int i = 0; i < ReportParameters.Count; i++)
                if (report_parameters[i].ParameterType == ES_R_ParameterTypes.DataSetReference &&
                    report_parameters[i].Value == null)
                    report_parameters[i].Table = GetTableForDataSet(report_parameters[i].Dataset_Name);
        }

        public object GetReportParameterValue(string value)
        {
            if (value.StartsWith("=Parameters!"))
            {
                value = value.Remove(0, 12);
                if (value.EndsWith(".Value"))
                    value = value.Remove(value.Length - 6);
                for (int i = 0; i < ReportParameters.Count; i++)
                    if (report_parameters[i].Name.ToUpper().Equals(value.ToUpper()))
                    {
                        if (!report_parameters[i].Nullable && report_parameters[i].Value == null)
                            throw new NullReferenceException("The report parameter is not set.");
                        return report_parameters[i].Value;
                    }
            }
            return null;
        }

        public int GetDataSetIndex(string name)
        {
            for (int i = 0; i < data_sets.Count; i++)
                if(data_sets[i].Name.ToUpper().Equals(name.ToUpper()))
                    return i;
            return -1;
        }
    }

    public class ES_R_ReportCollection : IList<ES_R_Report>, ICollection<ES_R_Report>, IEnumerable<ES_R_Report>
    {
        private List<ES_R_Report> reports = new List<ES_R_Report> { };

        public int Count { get { return reports.Count; } }

        public bool IsReadOnly { get { return false; } }

        public ES_R_Report this[int index] { get { return reports[index]; } set { reports[index] = value; } }

        public void Add(ES_R_Report value) { reports.Add(value); }

        public void Clear() { reports.Clear(); }

        public bool Contains(ES_R_Report value) { return reports.Contains(value); }

        public void CopyTo(ES_R_Report[] array, int arrayIndex) { reports.CopyTo(array, arrayIndex); }

        public int IndexOf(ES_R_Report value) { return reports.IndexOf(value); }

        public void Insert(int index, ES_R_Report value) { reports.Insert(index, value); }

        public bool Remove(ES_R_Report value) { return reports.Remove(value); }

        public void RemoveAt(int index) { reports.RemoveAt(index); }

        public IEnumerator<ES_R_Report> GetEnumerator() { return reports.GetEnumerator(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return reports.GetEnumerator(); }
    }

    public class ES_R_DataSource 
    {
        string name;
        string data_provider = "SQL";
        string connection_data_source = "<Server>";
        string connection_initial_catalog = "<Database>";
        string connection_user_id = "<Uid>";
        string connection_password = "<Pwd>";

        public string Name { get { return name; } set { name = value; } }
        public string Data_Provider { get { return data_provider; } set { data_provider = value; } }
        public string ConnectionDataSource { get { return connection_data_source; } set { connection_data_source = value; } }
        public string ConnectionInitialCatalog { get { return connection_initial_catalog; } set { connection_initial_catalog = value; } }
        public string ConnectionUserId { get { return connection_user_id; } set { connection_user_id = value; } }
        public string ConnectionPassword { get { return connection_password; } set { connection_password = value; } }

        public void LoadConnectionString(string connection_string)
        {

        }
    }

    public class ES_R_DataSourceCollection : IList<ES_R_DataSource>, ICollection<ES_R_DataSource>, IEnumerable<ES_R_DataSource>
    {
        private List<ES_R_DataSource> sources = new List<ES_R_DataSource> { };

        public int Count { get { return sources.Count; } }

        public bool IsReadOnly { get { return false; } }

        public ES_R_DataSource this[int index] { get { return sources[index]; } set { sources[index] = value; } }

        public void Add(ES_R_DataSource value) { sources.Add(value); }

        public void Clear() { sources.Clear(); }

        public bool Contains(ES_R_DataSource value) { return sources.Contains(value); }

        public void CopyTo(ES_R_DataSource[] array, int arrayIndex) { sources.CopyTo(array, arrayIndex); }

        public int IndexOf(ES_R_DataSource value) { return sources.IndexOf(value); }

        public void Insert(int index, ES_R_DataSource value) { sources.Insert(index, value); }

        public bool Remove(ES_R_DataSource value) { return sources.Remove(value); }

        public void RemoveAt(int index) { sources.RemoveAt(index); }

        public IEnumerator<ES_R_DataSource> GetEnumerator() { return sources.GetEnumerator(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return sources.GetEnumerator(); }
    }
    
    public class ES_R_DataField 
    {
        string name;
        string data_field;
        Type type;

        public string Name { get { return name; } set { name = value; } }
        public string DataField { get { return data_field; } set { data_field = value; } }
        public Type Type { get { return type; } set { type = value; } }
    }

    public class ES_R_QueryParameter 
    {
        string name;
        string value;

        public string Name { get { return name; } set { name = value; } }
        public string Value { get { return value; } set { this.value = value; } }
    }

    public class ES_R_DataSet 
    {
        string name;
        string data_source_name;
        string command_text;
        List<ES_R_DataField> fields = new List<ES_R_DataField> { };
        List<ES_R_QueryParameter> parameters = new List<ES_R_QueryParameter> { };
        DataTable table;

        public string Name { get { return name; } set { name = value; } }
        public string DataSourceName { get { return data_source_name; } set { data_source_name = value; } }
        public string CommandText { get { return command_text; } set { command_text = value; } }
        public DataTable Table { get { return table; } set { table = value; } }
        
        public List<ES_R_DataField> Fields { get { return fields; } }
        public List<ES_R_QueryParameter> Parameters { get { return parameters; } }
    }

    public class ES_R_DataSetCollection : IList<ES_R_DataSet>, ICollection<ES_R_DataSet>, IEnumerable<ES_R_DataSet>
    {
        private List<ES_R_DataSet> datasets = new List<ES_R_DataSet> { };

        public int Count { get { return datasets.Count; } }

        public bool IsReadOnly { get { return false; } }

        public ES_R_DataSet this[int index] { get { return datasets[index]; } set { datasets[index] = value; } }

        public void Add(ES_R_DataSet value) { datasets.Add(value); }

        public void Clear() { datasets.Clear(); }

        public bool Contains(ES_R_DataSet value) { return datasets.Contains(value); }

        public void CopyTo(ES_R_DataSet[] array, int arrayIndex) { datasets.CopyTo(array, arrayIndex); }

        public int IndexOf(ES_R_DataSet value) { return datasets.IndexOf(value); }

        public void Insert(int index, ES_R_DataSet value) { datasets.Insert(index, value); }

        public bool Remove(ES_R_DataSet value) { return datasets.Remove(value); }

        public void RemoveAt(int index) { datasets.RemoveAt(index); }

        public IEnumerator<ES_R_DataSet> GetEnumerator() { return datasets.GetEnumerator(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return datasets.GetEnumerator(); }
    }

    public class ES_R_ReportParameter
    {
        string name;
        Type type;
        string prompt;
        ES_R_ParameterTypes param_type;
        bool nullable = false;
        bool allow_blank = false;
        object value;
        object label;

        string dataset_name;
        string dataset_value_field;
        string dataset_label_field;
        DataTable table;

        public string Name { get { return name; } set { name = value; } }
        public Type Type { get { return type; } set { type = value; } }
        public string Prompt { get { return prompt; } set { prompt = value; } }
        public ES_R_ParameterTypes ParameterType { get { return param_type; } set { param_type = value; } }
        public bool Nullable { get { return nullable; } set { nullable = value; } }
        public bool AllowBlank { get { return allow_blank; } set { allow_blank = value; } }
        public object Value { get { return this.value; } set { this.value = value; } }
        public object Label { get { return this.label; } set { this.label = value; } }

        public string Dataset_Name 
        {
            get 
            {
                if (ParameterType != ES_R_ParameterTypes.DataSetReference)
                    return null;
                return dataset_name;
            }
            set { dataset_name = value; }
        }
        public string Dataset_ValueField
        {
            get
            {
                if (ParameterType != ES_R_ParameterTypes.DataSetReference)
                    return null; 
                return dataset_value_field;
            }
            set { dataset_value_field = value; }
        }
        public string Dataset_LabelField
        {
            get
            {
                if (ParameterType != ES_R_ParameterTypes.DataSetReference)
                    return null; 
                return dataset_label_field;
            }
            set { dataset_label_field = value; }
        }

        public DataTable Table { get { return table; } set { table = value; } }

        public static Type GetType(string value)
        {
            switch (value.ToLower())
            {
                case "string":
                    return typeof(string);
                case "system.string":
                    goto case "string";
                case "int32":
                    return typeof(int);
                case "system.int32":
                    goto case "int32";
                default:
                    goto case "string";
            }
        }
    }

    public enum ES_R_ParameterTypes { DataSetReference, ParameterValues }

    public class ES_R_ReportParameterCollection : IList<ES_R_ReportParameter>, ICollection<ES_R_ReportParameter>, IEnumerable<ES_R_ReportParameter>
    {
        private List<ES_R_ReportParameter> parameter = new List<ES_R_ReportParameter> { };

        public int Count { get { return parameter.Count; } }

        public bool IsReadOnly { get { return false; } }

        public ES_R_ReportParameter this[int index] { get { return parameter[index]; } set { parameter[index] = value; } }

        public void Add(ES_R_ReportParameter value) { parameter.Add(value); }

        public void Clear() { parameter.Clear(); }

        public bool Contains(ES_R_ReportParameter value) { return parameter.Contains(value); }

        public void CopyTo(ES_R_ReportParameter[] array, int arrayIndex) { parameter.CopyTo(array, arrayIndex); }

        public int IndexOf(ES_R_ReportParameter value) { return parameter.IndexOf(value); }

        public void Insert(int index, ES_R_ReportParameter value) { parameter.Insert(index, value); }

        public bool Remove(ES_R_ReportParameter value) { return parameter.Remove(value); }

        public void RemoveAt(int index) { parameter.RemoveAt(index); }

        public IEnumerator<ES_R_ReportParameter> GetEnumerator() { return parameter.GetEnumerator(); }

        public ES_R_ReportParameter[] ToArray() { return parameter.ToArray(); }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return parameter.GetEnumerator(); }
    }
}
